package com.sinping.qh.api.auth;


import com.sinping.qh.api.support.Const;
import com.sinping.qh.api.support.ConstEum;
import com.sinping.qh.api.support.MediaTypes;
import com.sinping.qh.api.support.ResDto;
import com.sinping.qh.domain.auth.Resource;
import com.sinping.qh.dto.auth.ResourceDTO;
import com.sinping.qh.service.auth.IResourceService;
import com.sinping.qh.service.auth.IRoleResourceService;
import com.sinping.qh.utils.auth.ValidateParanUtil;
import com.sinping.qh.utils.mapper.JsonMapper;
import com.sinping.qh.utils.misc.IdGenerator;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author 杨云博
 * @since 2017-12-18
 */
@Api(value = "Admin资源管理", description = "Admin资源管理API")
@RestController
@RequestMapping(value = Const.ADMIN_URI + "resource", name = "资源管理")
public class ResourceEndPoint {

    private final static Logger logger = LoggerFactory.getLogger(ResourceEndPoint.class);

    @Autowired
    private IResourceService resourceService;

    @Autowired
    private IRoleResourceService roleResourceService;

    /**
     * @param msg 资源对象
     *            return com.sinping.woniu.api.support.ResDto
     * @方法名称: getResourceListByResource
     * @功能描述: 获取资源列表
     * @作者:杨云博
     * @创建时间:2017/12/19 14:00
     */

    @ApiOperation(httpMethod = "GET", value = "获取资源列表", consumes = MediaTypes.TEXT_HTML_UTF_8)
    @RequestMapping(method = RequestMethod.GET, name = "获取资源列表")
    public ResDto resource(@ApiParam(name = "msg", value = "{\"parent_id\":\"xxxxxxx\",\"lev\":\"1\"}")
                           @RequestParam String msg) {
        ResDto result = new ResDto();
        ResourceDTO resource = JsonMapper.defaultMapper().fromJson(msg, ResourceDTO.class);
        List<ResourceDTO> list = resourceService.getResourceListTree(resource.toResource());
        result = new ResDto(ConstEum.SUCCESS, JsonMapper.defaultMapper().toJson(list));
        return result;
    }

    /**
     * @param msg return com.sinping.woniu.api.support.ResDto
     * @方法名称: addResource
     * @功能描述: 添加资源
     * @作者:杨云博
     * @创建时间:2017/12/20 11:50
     */
    @ApiOperation(httpMethod = "POST", value = "添加资源", consumes = MediaTypes.TEXT_HTML_UTF_8)
    @RequestMapping(method = RequestMethod.POST, name = "添加资源")
    public ResDto addResource(@ApiParam(name = "msg", value = "{\"name\":\"xxxxxx\",\"url\":\"/api/v1/xxxx/\",\"type\":\"0\",\"lev\":\"1\",<br>\"permission\":\"add\",\"parent_id\":\"xxxxxxx\",\"request_type\":\"POST\",<br>\"code\":\"1000010\"}")
                              @RequestParam(required = true) String msg ) {
        ResDto result = new ResDto();
        ResourceDTO resource = JsonMapper.defaultMapper().fromJson(msg, ResourceDTO.class);
        //验证参数
        if (resource == null) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }
        if (StringUtils.isEmpty(resource.getName())) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }
        if (null == resource.getLev()) {
            result = new ResDto(Const.PARAM_ERROR, "msg.add.fail");
            return result;
        }
        if (StringUtils.isEmpty(resource.getUrl())) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }

        if (StringUtils.isEmpty(resource.getRequestType())) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }

        if (this.resourceService.isExistUriAndRequestType(resource.getUrl(),resource.getRequestType(),null)) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }

        List<Integer> resoureTypeList = new ArrayList<>();
        resoureTypeList.add(Const.RESOURE_TYPE_BUTTON);
        resoureTypeList.add(Const.RESOURE_TYPE_MEUM);
        if (null == resource.getType() || !ValidateParanUtil.ValidateIngterParan(resource.getType(),resoureTypeList)) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }
        if (null == resource.getCode()) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }
        if (resource.getLev() != 1 && (StringUtils.isEmpty(resource.getParentId()))) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }
        if (resource.getLev() != 1 && null != resource.getParentId() && !"".equals(resource.getParentId())) {
            Resource re = resourceService.selectById(resource.getParentId());
            if (re == null) {
                result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
                return result;
            }
        }
        List<Integer> statusList = new ArrayList<>();
        statusList.add(Const.STATUS_EFFECTIVE);
        statusList.add(Const.STATUS_INVALID);
        if(null == resource.getStatus() || !ValidateParanUtil.ValidateIngterParan(resource.getStatus(),statusList)){
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }
        //资源状态
        //resource.setStatus(Const.STATUS_EFFECTIVE);
        //资源创建时间
        resource.setCreateTime(new Date());
        String id = IdGenerator.uuid2();
        resource.setId(id);
        try {
            boolean res = resourceService.insert(resource.toResource());
            if (res) {
                result = new ResDto(ConstEum.SUCCESS);
                Map<String,Object> map = new HashMap<>();
                map.put("id",id);
                result.setDatas(JsonMapper.defaultMapper().toJson(map));
            } else {
                result = new ResDto(Const.SERVER_ERROR, "msg.add.fail");
            }
        } catch (DataIntegrityViolationException e){
            logger.error(e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            result = new ResDto(Const.SERVER_ERROR, "msg.handle.fail");
        }

        return result;
    }

    /**
     * @param msg return com.sinping.woniu.api.support.ResDto
     * @方法名称: updateResource
     * @功能描述: 修改资源
     * @作者:杨云博
     * @创建时间:2017/12/20 13:50
     */
    @ApiParam("Resource")
    @ApiOperation(httpMethod = "PUT", value = "修改资源信息", consumes = MediaTypes.TEXT_HTML_UTF_8)
    @RequestMapping(method = RequestMethod.PUT, name = "修改资源信息")
    public ResDto updateResource(@ApiParam(name = "msg", value = "{\"id\":\"xxxxxxxxxx\",\"name\":\"xxxxxx\",\"url\":\"/api/v1/xxxx/\",\"type\":\"0\",<br>\"lev\":\"1\",\"permission\":\"add\",\"parentId\":\"xxxxxxx\",\"code\":\"1000010\"}") @RequestParam String msg) {
        ResDto result = new ResDto();
        ResourceDTO resource = JsonMapper.defaultMapper().fromJson(msg, ResourceDTO.class);
        //验证参数
        if (resource == null) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }
        if (StringUtils.isEmpty(resource.getId())) {
            result = new ResDto(Const.PARAM_ERROR, "msg.handle.fail");
            return result;
        }

        if (StringUtils.isEmpty(resource.getUrl())) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }
        if (StringUtils.isEmpty(resource.getRequestType())) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }
        if (this.resourceService.isExistUriAndRequestType(resource.getUrl(),resource.getRequestType(),resource.getId())) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }

        if (StringUtils.isEmpty(resource.getName())) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }
        if (null == resource.getLev()) {
            result = new ResDto(Const.PARAM_ERROR, "msg.add.fail");
            return result;
        }
        List<Integer> resoureTypeList = new ArrayList<>();
        resoureTypeList.add(Const.RESOURE_TYPE_BUTTON);
        resoureTypeList.add(Const.RESOURE_TYPE_MEUM);

        if (null == resource.getType() || !ValidateParanUtil.ValidateIngterParan(resource.getType(),resoureTypeList)) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }
        if (null == resource.getCode()) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }
        if (resource.getLev() != 1 && (StringUtils.isEmpty(resource.getParentId()))) {
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }
        if (resource.getLev() != 1 && null != resource.getParentId() && !"".equals(resource.getParentId())) {
            Resource re = resourceService.selectById(resource.getParentId());
            if (re == null || re.getId() == resource.getId()) {
                result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
                return result;
            }
        }
        List<Integer> statusList = new ArrayList<>();
        statusList.add(Const.STATUS_EFFECTIVE);
        statusList.add(Const.STATUS_INVALID);
        if(null == resource.getStatus() || !ValidateParanUtil.ValidateIngterParan(resource.getStatus(),statusList)){
            result = new ResDto(Const.PARAM_ERROR, "msg.param.error");
            return result;
        }

        try {
            //资源创建时间
            resource.setUpdateTime(new Date());
            boolean res = resourceService.updateById(resource.toResource());
            if (res) {
                result = new ResDto(ConstEum.SUCCESS);
            } else {
                result = new ResDto(Const.SERVER_ERROR, "msg.update.fail");
            }
        } catch (DataIntegrityViolationException e){
            logger.error(e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            result = new ResDto(Const.SERVER_ERROR, "msg.handle.fail");
        }
        return result;
    }

    /**
     * @param id return com.sinping.woniu.api.support.ResDto
     * @方法名称: deleteResourceById
     * @功能描述: 删除资源信息
     * @作者:杨云博
     * @创建时间:2017/12/20 13:58
     */
    @ApiParam("Resource")
    @ApiOperation(httpMethod = "DELETE", value = "删除资源信息", notes = "资源ID")
    @RequestMapping(value = "/${id}", method = RequestMethod.DELETE, name = "删除资源信息")
    public ResDto deleteResourceById(@PathVariable String id) {
        ResDto result = new ResDto();
        if (StringUtils.isEmpty(id)) {
            result = new ResDto(Const.PARAM_ERROR, "msg.handle.fail");
            return result;
        }

        try {
            if (roleResourceService.isUseResourceId(id)) {
                result = new ResDto(Const.SERVER_ERROR, "msg.delete.fail");
                return result;
            }

            boolean res = resourceService.deleteById(id);
            if (res) {
                result = new ResDto(ConstEum.SUCCESS);
            } else {
                result = new ResDto(Const.SERVER_ERROR, "msg.delete.fail");
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            result = new ResDto(Const.SERVER_ERROR, "msg.handle.fail");
        }
        return result;
    }

    /**
     * @param id return com.sinping.woniu.api.support.ResDto
     * @方法名称: getResourceById
     * @功能描述: 获取资源id
     * @作者:杨云博
     * @创建时间:2017/12/21 11:14
     */
    @ApiParam("Resource")
    @ApiOperation(httpMethod = "GET", value = "获取资源详情")
    @RequestMapping(value = "/${id}", method = RequestMethod.GET, name = "获取资源详情")
    public ResDto getResourceById(@PathVariable String id) {
        ResDto result = new ResDto();
        Resource resource = resourceService.selectById(id);
        if (resource == null) {
            result = new ResDto(Const.DATA_ERROR, "msg.data.not.exist");
            return result;
        }
        ResourceDTO resourceDTO = new ResourceDTO(resource);
        result = new ResDto(ConstEum.SUCCESS, JsonMapper.defaultMapper().toJson(resourceDTO));
        return result;
    }
}

